using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace DMTT.Workflow.Activities.Design
{
    public class TreeViewLinkItem : LinkItem
	{

        #region Private Variables

        private const int INDENT_WIDTH = 20;
        private const int LINE_WIDTH_TOP = 1;
        private const int LINE_WIDTH_INNER = 2;
        
        private TreeNode m_sourceNode;
        private TreeNode m_destinationNode;

        #endregion


        #region Constructors

        public TreeViewLinkItem()
        {
        }

        public TreeViewLinkItem(
            TreeNode sourceNode,
            TreeNode destinationNode)
            : this()
        {
            m_sourceNode = sourceNode;
            m_destinationNode = destinationNode;
            this.Refresh();
        }

        #endregion


        #region Public Properties

        public TreeNode SourceNode
        {
            get { return m_sourceNode; }
            set { m_sourceNode = value; }
        }

        public TreeNode DestinationNode
        {
            get { return m_destinationNode; }
            set { m_destinationNode = value; }
        }

        public override Point StartPoint
        {
            get { return this.GetTreeNodePos(m_sourceNode, true); }
            set { base.StartPoint = value; }
        }

        public override Point EndPoint
        {
            get { return this.GetTreeNodePos(m_destinationNode, false) ; }
            set { this.EndPoint = value; }
        }

        #endregion


        #region Private Functions

        private Point GetTreeNodePos(TreeNode node, bool start)
        {
            int offset = 0;
            if (start)
                offset = node.TreeView.Width;
            return new Point(
                node.TreeView.Location.X + offset,
                node.TreeView.Location.Y + node.Bounds.Location.Y +
                (node.Bounds.Height / 2) + 2);
        }

        #endregion


        #region Public Functions

        public void Refresh()
        {
            Point[] pointsTop = new Point[] { };
            Point[] pointsInner = new Point[] { };
            Point[] pointsBottom = new Point[] { };

            int halfWidthInner = LINE_WIDTH_INNER / 2;
            int halfWidthInnerTop = halfWidthInner - 1;
            int halfWidthInnerBottom = halfWidthInner;

            if (this.StartPoint.Y <= this.EndPoint.Y)
            {
                pointsTop = new Point[4]{
											new Point(this.StartPoint.X, this.StartPoint.Y - halfWidthInnerTop),
											new Point(this.StartPoint.X + halfWidthInnerTop + INDENT_WIDTH, this.StartPoint.Y - halfWidthInnerTop),
											new Point(this.EndPoint.X + halfWidthInnerTop - INDENT_WIDTH, this.EndPoint.Y - halfWidthInnerTop),
											new Point(this.EndPoint.X, this.EndPoint.Y - halfWidthInnerTop)
										};
                pointsInner = new Point[4]{
											  this.StartPoint,
											  new Point(this.StartPoint.X + INDENT_WIDTH, this.StartPoint.Y),
											  new Point(this.EndPoint.X - INDENT_WIDTH, this.EndPoint.Y),
											  this.EndPoint
										  };
                pointsBottom = new Point[4]{
											   new Point(this.StartPoint.X, this.StartPoint.Y + halfWidthInnerBottom),
											   new Point(this.StartPoint.X - halfWidthInnerBottom + INDENT_WIDTH, this.StartPoint.Y + halfWidthInnerBottom),
											   new Point(this.EndPoint.X - halfWidthInnerBottom - INDENT_WIDTH, this.EndPoint.Y + halfWidthInnerBottom),
											   new Point(this.EndPoint.X, this.EndPoint.Y + halfWidthInnerBottom)
										   };
            }
            else
            {
                pointsTop = new Point[4]{
											new Point(this.StartPoint.X, this.StartPoint.Y - halfWidthInnerTop),
											new Point(this.StartPoint.X - halfWidthInnerTop + INDENT_WIDTH, this.StartPoint.Y - halfWidthInnerTop),
											new Point(this.EndPoint.X - LINE_WIDTH_TOP - INDENT_WIDTH, this.EndPoint.Y - halfWidthInnerTop),
											new Point(this.EndPoint.X, this.EndPoint.Y - halfWidthInnerTop)
										};
                pointsInner = new Point[4]{
											  this.StartPoint,
											  new Point(this.StartPoint.X + INDENT_WIDTH, this.StartPoint.Y),
											  new Point(this.EndPoint.X - INDENT_WIDTH, this.EndPoint.Y),
											  this.EndPoint
										  };
                pointsBottom = new Point[4]{
											   new Point(this.StartPoint.X, this.StartPoint.Y + halfWidthInnerBottom),
											   new Point(this.StartPoint.X + halfWidthInnerBottom + INDENT_WIDTH, this.StartPoint.Y + halfWidthInnerBottom),
											   new Point(this.EndPoint.X + halfWidthInnerBottom - INDENT_WIDTH, this.EndPoint.Y + halfWidthInnerBottom),
											   new Point(this.EndPoint.X, this.EndPoint.Y + halfWidthInnerBottom)
										   };
            }

            byte[] types = new byte[4]{
										  (byte)PathPointType.Start,
										  (byte)PathPointType.Line,
										  (byte)PathPointType.Line,
										  (byte)PathPointType.Line
									  };

            this.PathTop = new GraphicsPath(pointsTop, types);
            this.PathInner = new GraphicsPath(pointsInner, types);
            this.PathBottom = new GraphicsPath(pointsBottom, types);
        }

        #endregion

    }
}
